<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VSCode风格行号演示</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #1e1e1e;
            color: #d4d4d4;
            margin: 0;
            padding: 20px;
        }
        
        .demo-container {
            max-width: 1200px;
            margin: 0 auto;
        }
        
        .demo-title {
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 20px;
            color: #007acc;
            text-align: center;
        }
        
        .demo-description {
            text-align: center;
            margin-bottom: 30px;
            color: #858585;
            line-height: 1.6;
        }
        
        .editor-demo {
            display: flex;
            margin-bottom: 30px;
            border: 1px solid #3c3c3c;
            border-radius: 5px;
            overflow: hidden;
        }
        
        /* VSCode风格的行号样式 */
        .line-numbers {
            position: relative;
            width: 50px;
            background-color: #1e1e1e;
            border-right: 1px solid #3c3c3c;
            overflow: hidden;
            box-sizing: border-box;
        }
        
        .line-number {
            position: absolute;
            width: 100%;
            height: 21px;
            line-height: 21px;
            padding: 0 8px 0 0;
            display: flex;
            align-items: center;
            justify-content: flex-end;
            font-size: 14px;
            color: #858585;
            user-select: none;
            pointer-events: none;
            box-sizing: border-box;
            font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Source Code Pro', 'Consolas', 'Monaco', 'Courier New', monospace;
        }
        
        .line-number.current-line {
            color: #d4d4d4;
            background-color: rgba(255, 255, 255, 0.05);
        }
        
        .line-number:hover {
            color: #d4d4d4;
            background-color: rgba(255, 255, 255, 0.02);
        }
        
        .code-editor {
            flex: 1;
            background-color: #1e1e1e;
            color: #d4d4d4;
            border: none;
            outline: none;
            font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Source Code Pro', 'Consolas', 'Monaco', 'Courier New', monospace;
            font-size: 14px;
            line-height: 21px;
            padding: 10px;
            overflow: auto;
            white-space: pre-wrap;
            word-wrap: break-word;
            caret-color: #d4d4d4;
            box-sizing: border-box;
            min-height: 400px;
        }
        
        .controls {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        
        .control-button {
            background-color: #007acc;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 3px;
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.2s;
        }
        
        .control-button:hover {
            background-color: #005a9e;
        }
        
        .control-button.secondary {
            background-color: #3c3c3c;
        }
        
        .control-button.secondary:hover {
            background-color: #4c4c4c;
        }
        
        .features {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            margin-top: 30px;
        }
        
        .feature-card {
            background-color: #252526;
            padding: 20px;
            border-radius: 5px;
            border: 1px solid #3c3c3c;
        }
        
        .feature-title {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 10px;
            color: #007acc;
        }
        
        .feature-description {
            color: #858585;
            line-height: 1.6;
        }
        
        .code-example {
            background-color: #1e1e1e;
            padding: 15px;
            border-radius: 3px;
            margin-top: 10px;
            font-family: 'JetBrains Mono', monospace;
            font-size: 12px;
            overflow-x: auto;
        }
    </style>
</head>
<body>
    <div class="demo-container">
        <h1 class="demo-title">VSCode风格行号演示</h1>
        <p class="demo-description">
            这是一个完全模仿VSCode行号显示效果的演示。行号与代码内容完美对齐，
            支持滚动同步、当前行高亮等VSCode特性。
        </p>
        
        <div class="controls">
            <button class="control-button" onclick="updateDemoLineNumbers()">更新行号</button>
            <button class="control-button" onclick="addMoreLines()">添加更多行</button>
            <button class="control-button" onclick="clearContent()">清空内容</button>
            <button class="control-button secondary" onclick="toggleCurrentLine()">切换当前行高亮</button>
            <button class="control-button secondary" onclick="testAlignment()">测试对齐</button>
            <button class="control-button secondary" onclick="resetDemo()">重置演示</button>
        </div>
        
        <div class="editor-demo">
            <div class="line-numbers" id="demo-line-numbers">
                <!-- 行号将通过JavaScript动态生成 -->
            </div>
            <textarea class="code-editor" id="demo-editor" placeholder="在这里输入代码...">// VSCode风格行号演示
function vscodeStyleLineNumbers() {
    // 这是一个演示函数
    console.log("Hello, VSCode style!");
    
    // 支持多行代码
    const lines = [
        "第一行代码",
        "第二行代码", 
        "第三行代码"
    ];
    
    lines.forEach((line, index) => {
        console.log(`行 ${index + 1}: ${line}`);
    });
    
    return "演示完成";
}

// 调用函数
vscodeStyleLineNumbers();</textarea>
        </div>
        
        <div class="features">
            <div class="feature-card">
                <div class="feature-title">完美对齐</div>
                <div class="feature-description">
                    行号与代码内容完全对齐，无论字体大小、行高如何变化，都能保持精确的对齐状态。
                </div>
                <div class="code-example">
// 行号位置计算
const topPosition = (lineIndex - 1) * lineHeight + paddingTop;
lineNumber.style.top = topPosition + 'px';
                </div>
            </div>
            
            <div class="feature-card">
                <div class="feature-title">滚动同步</div>
                <div class="feature-description">
                    使用transform实现平滑的滚动同步，行号与代码内容始终保持同步滚动。
                </div>
                <div class="code-example">
// 滚动同步
const scrollTop = editor.scrollTop;
lineNumbers.style.transform = `translateY(-${scrollTop}px)`;
                </div>
            </div>
            
            <div class="feature-card">
                <div class="feature-title">当前行高亮</div>
                <div class="feature-description">
                    支持当前行高亮显示，提供更好的视觉反馈和用户体验。
                </div>
                <div class="code-example">
// 当前行高亮
.line-number.current-line {
    color: #d4d4d4;
    background-color: rgba(255, 255, 255, 0.05);
}
                </div>
            </div>
            
            <div class="feature-card">
                <div class="feature-title">性能优化</div>
                <div class="feature-description">
                    使用文档片段和防抖机制，确保大文件也能流畅显示行号。
                </div>
                <div class="code-example">
// 性能优化
const fragment = document.createDocumentFragment();
// 批量添加行号元素
lineNumbers.appendChild(fragment);
                </div>
            </div>
        </div>
    </div>

    <script>
        let currentLineHighlight = true;
        
        // 初始化演示
        function initDemo() {
            const editor = document.getElementById('demo-editor');
            const lineNumbers = document.getElementById('demo-line-numbers');
            
            // 更新行号
            updateLineNumbers();
            
            // 添加滚动同步
            editor.addEventListener('scroll', syncScroll);
            
            // 添加输入事件
            editor.addEventListener('input', () => {
                setTimeout(updateLineNumbers, 0);
            });
        }
        
        // 更新行号
        function updateLineNumbers() {
            const editor = document.getElementById('demo-editor');
            const lineNumbers = document.getElementById('demo-line-numbers');
            
            const lines = editor.value.split('\n');
            const lineCount = lines.length;
            const lineHeight = 21;
            const paddingTop = 10;
            
            // 清空现有行号
            lineNumbers.innerHTML = '';
            
            // 创建文档片段
            const fragment = document.createDocumentFragment();
            
            // 添加行号
            for (let i = 1; i <= lineCount; i++) {
                const lineDiv = document.createElement('div');
                lineDiv.className = 'line-number';
                lineDiv.textContent = i;
                lineDiv.setAttribute('data-line', i);
                
                const topPosition = (i - 1) * lineHeight + paddingTop;
                lineDiv.style.top = topPosition + 'px';
                
                // 添加点击事件
                lineDiv.addEventListener('click', () => {
                    console.log('点击行号:', i);
                });
                
                fragment.appendChild(lineDiv);
            }
            
            lineNumbers.appendChild(fragment);
            
            // 设置容器高度
            const totalHeight = lineCount * lineHeight + 20;
            lineNumbers.style.height = totalHeight + 'px';
            
            // 同步滚动
            syncScroll();
        }
        
        // 同步滚动
        function syncScroll() {
            const editor = document.getElementById('demo-editor');
            const lineNumbers = document.getElementById('demo-line-numbers');
            
            const scrollTop = editor.scrollTop;
            lineNumbers.style.transform = `translateY(-${scrollTop}px)`;
            
            if (currentLineHighlight) {
                highlightCurrentLine();
            }
        }
        
        // 高亮当前行
        function highlightCurrentLine() {
            const editor = document.getElementById('demo-editor');
            const lineNumbers = document.getElementById('demo-line-numbers');
            
            // 移除所有当前行高亮
            const currentLines = lineNumbers.querySelectorAll('.line-number.current-line');
            currentLines.forEach(line => line.classList.remove('current-line'));
            
            // 计算当前行
            const scrollTop = editor.scrollTop;
            const lineHeight = 21;
            const paddingTop = 10;
            const currentLineIndex = Math.floor((scrollTop + editor.clientHeight / 2 - paddingTop) / lineHeight) + 1;
            
            // 高亮当前行
            const currentLineElement = lineNumbers.querySelector(`[data-line="${currentLineIndex}"]`);
            if (currentLineElement) {
                currentLineElement.classList.add('current-line');
            }
        }
        
        // 控制函数
        function updateDemoLineNumbers() {
            updateLineNumbers();
            console.log('行号已更新');
        }
        
        function addMoreLines() {
            const editor = document.getElementById('demo-editor');
            const additionalCode = `

// 添加的额外代码
function additionalFunction() {
    for (let i = 0; i < 10; i++) {
        console.log(\`额外行 \${i + 1}\`);
    }
}

// 更多代码示例
const array = [1, 2, 3, 4, 5];
array.forEach(item => {
    console.log(\`数组项: \${item}\`);
});`;
            
            editor.value += additionalCode;
            updateLineNumbers();
            console.log('已添加更多行');
        }
        
        function clearContent() {
            const editor = document.getElementById('demo-editor');
            editor.value = '';
            updateLineNumbers();
            console.log('内容已清空');
        }
        
        function toggleCurrentLine() {
            currentLineHighlight = !currentLineHighlight;
            const button = event.target;
            button.textContent = currentLineHighlight ? '关闭当前行高亮' : '开启当前行高亮';
            
            if (!currentLineHighlight) {
                const lineNumbers = document.getElementById('demo-line-numbers');
                const currentLines = lineNumbers.querySelectorAll('.line-number.current-line');
                currentLines.forEach(line => line.classList.remove('current-line'));
            }
            
            console.log('当前行高亮:', currentLineHighlight ? '开启' : '关闭');
        }
        
        function testAlignment() {
            const editor = document.getElementById('demo-editor');
            const lineNumbers = document.getElementById('demo-line-numbers');
            
            const lines = editor.value.split('\n');
            const lineCount = lines.length;
            const lineNumberElements = lineNumbers.querySelectorAll('.line-number');
            
            console.log('=== 对齐测试 ===');
            console.log('代码行数:', lineCount);
            console.log('行号数量:', lineNumberElements.length);
            console.log('对齐状态:', lineCount === lineNumberElements.length ? '✓ 完美' : '✗ 不匹配');
            
            // 检查前几行的位置
            for (let i = 1; i <= Math.min(5, lineCount); i++) {
                const lineNumber = lineNumbers.querySelector(`[data-line="${i}"]`);
                if (lineNumber) {
                    const topPosition = parseInt(lineNumber.style.top);
                    const expectedTop = (i - 1) * 21 + 10;
                    console.log(`行 ${i}: 位置 ${topPosition}px, 期望 ${expectedTop}px, 对齐: ${Math.abs(topPosition - expectedTop) <= 1 ? '✓' : '✗'}`);
                }
            }
        }
        
        function resetDemo() {
            const editor = document.getElementById('demo-editor');
            editor.value = `// VSCode风格行号演示
function vscodeStyleLineNumbers() {
    console.log("Hello, VSCode style!");
    return "演示完成";
}`;
            
            currentLineHighlight = true;
            const button = document.querySelector('.control-button.secondary');
            if (button) button.textContent = '切换当前行高亮';
            
            updateLineNumbers();
            console.log('演示已重置');
        }
        
        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', initDemo);
    </script>
</body>
</html> 